package org.wang.generalcode.modules.sys.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.wang.generalcode.modules.sys.constant.SystemConstants;
import org.wang.generalcode.modules.sys.converter.RoleConverter;
import org.wang.generalcode.modules.sys.mapper.RoleMapper;
import org.wang.generalcode.modules.sys.mapper.UserRoleMapper;
import org.wang.generalcode.modules.sys.pojo.entity.Role;
import org.wang.generalcode.modules.sys.pojo.entity.RoleMenu;
import org.wang.generalcode.modules.sys.pojo.model.Option;
import org.wang.generalcode.modules.sys.pojo.params.RolePageParams;
import org.wang.generalcode.modules.sys.pojo.params.RoleParams;
import org.wang.generalcode.modules.sys.pojo.vo.RoleVO;
import org.wang.generalcode.modules.sys.service.IRoleMenuService;
import org.wang.generalcode.modules.sys.service.IRoleService;

import java.util.List;
import java.util.Set;

/**
 * 角色表 服务实现类
 *
 * @author wz
 * @since 2024-08-08
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

	@Resource
	private  RoleConverter roleConverter;

	@Resource
	private UserRoleMapper userRoleMapper;

	@Resource
	private IRoleMenuService roleMenuService;

	@Override
	public IPage<RoleVO> selectRolePage(IPage<RoleVO> page, RolePageParams queryParams) {
		return page.setRecords(baseMapper.selectRolePage(page, queryParams));
	}

	@Override
	public List<Option<Long>> listRoleOptions() {


		// 查询数据
		List<Role> roleList = this.list(new LambdaQueryWrapper<Role>()
				.ne(!isRoot(), Role::getCode, SystemConstants.ROOT_ROLE_CODE)
				.select(Role::getId, Role::getName)
				.orderByAsc(Role::getSort)
		);

		// 实体转换
		return roleConverter.entities2Options(roleList);
	}

	@Override
	public List<Long> getRoleMenuIds(Long roleId) {
		return baseMapper.listMenuIdsByRoleId(roleId);
	}

	@Override
	public boolean saveRole(RoleParams roleParams) {
		Long roleId = roleParams.getId();

		// 编辑角色时，判断角色是否存在
		Role oldRole = null;
		if (roleId != null) {
			oldRole = this.getById(roleId);
			Assert.isTrue(oldRole != null, "角色不存在");
		}

		String roleCode = roleParams.getCode();
		long count = this.count(new LambdaQueryWrapper<Role>()
				.ne(roleId != null, Role::getId, roleId)
				.and(wrapper ->
						wrapper.eq(Role::getCode, roleCode).or().eq(Role::getName, roleParams.getName())
				));
		Assert.isTrue(count == 0, "角色名称或角色编码已存在，请修改后重试！");

		// 实体转换
		Role role = roleConverter.toEntity(roleParams);

		boolean result = this.saveOrUpdate(role);

		return result;
	}

	@Override
	public boolean assignMenusToRole(Long roleId, List<Long> menuIds) {
		Role role = this.getById(roleId);
		Assert.isTrue(role != null, "角色不存在");

		// 删除角色菜单
		roleMenuService.remove(
				new LambdaQueryWrapper<RoleMenu>()
						.eq(RoleMenu::getRoleId, roleId)
		);
		// 新增角色菜单
		if (CollectionUtil.isNotEmpty(menuIds)) {
			List<RoleMenu> roleMenus = menuIds
					.stream()
					.map(menuId -> new RoleMenu(roleId, menuId))
					.toList();
			roleMenuService.saveBatch(roleMenus);
		}

		// 刷新角色的权限缓存
//		roleMenuService.refreshRolePermsCache(role.getCode());

		return true;
	}


	/**
	 * 是否超级管理员
	 * <p>
	 * 超级管理员忽视任何权限判断
	 */
	public boolean isRoot() {
		Object loginId = StpUtil.getLoginId();
		Set<String> roles = userRoleMapper.getRoleCode(Convert.toInt(loginId));
		return roles.contains(SystemConstants.ROOT_ROLE_CODE);
	}

}
